;-----------------------------------------------------------------------------------------------
;
; flat assembler interface for Fresh RAD IDE
;
; Copyright (c) 1999-2003, Tomasz Grysztar.
; Copyright (c) 2003, John Found
; All rights reserved.
;
;   This file is modified version of the fasm.inc file from
; FASMW package.
;
;-----------------------------------------------------------------------------------------------

macro dm string { db string,0 }

;uglobal
;  include "fasm\variable.inc"
;endg

iglobal
  _section_environment db 'Environment',0
  _include             db 'INCLUDE',0
endg


;uglobal
;  bytes_count           dd ?
;  systime               SYSTEMTIME
;
;  start_time            dd ?
;  preprocess_time       dd ?
;  parsing_time          dd ?
;  capturing_time        dd ?
;  assembling_time       dd ?
;  last_pass_time        dd ?
;  values_time           dd ?
;
;  total_time            dd ?
;
;  exit_code             dd ?
;  buffer                rb 1000h
;endg

;;
;; Fresh internal variables not related to FASM compiler
;uglobal
;  CompiledFileName      dd ?
;;  ptrIniPath            dd ?
;
;  param_buffer          rd 10h
;  path_buffer           rb 1000h
;
;  hfile                 dd ?
;
;  error_data_size       dd ?
;  compiler_memory       dd ?
;
;  ptrMemoryAllocated    dd ?
;
;  save_stack_pointer    dd ?
;endg



;align 16

include 'fasm\expressi.inc'
include 'fasm\preproce.inc'
include 'fasm\parser.inc'
include 'fasm\assemble.inc'
include 'fasm\formats.inc'
include 'fasm\x86_64.inc'
include 'fasm\errors.inc'
include 'fasm\tables.inc'


proc InitCompiler
begin
	pusha
	
        mov     [passes_limit], $80

        mov     dword [locals_counter], '0000'
        mov     dword [locals_counter+4], '0000'
        mov     [locals_counter], 7

;        mov     edi,case_table
;        xor     ebx,ebx
;        mov     esi,100h
;
;.make_case_table:
;        invoke  CharLower,ebx
;        stosb
;        inc     bl
;        dec     esi
;        jnz     .make_case_table

        mov     edi,characters
        mov     ecx,100h
        xor     al,al

.make_characters_table:
        stosb
        inc     al
        loop    .make_characters_table

        mov     esi,characters+'a'
        mov     edi,characters+'A'
        mov     ecx,26
        rep     movsb
        mov     edi,characters
        mov     esi,symbol_characters+1
        movzx   ecx,byte [esi-1]
        xor     eax,eax

.convert_table:
        lodsb
        mov     byte [edi+eax],0
        loop    .convert_table

;        stdcall StrPtr, [hIniFileName]
;        mov     [ptrIniPath], eax

	popa
	
        return
endp


;uglobal
; fmsg TFreshMsg
; hStrFileName   dd ?
;endg


;----------------------------------------------------------
; Prepares the compiler for compilation, allocating needed
; memory, preparing filename, path, etc.
; It is good to call from main thread.
;
; Returns:
;   eax - TRUE if compiler is ready.
;         FALSE if there is no free memory.
;----------------------------------------------------------
proc PrepareForCompilation, .hFileName
begin
	pusha
; Init virtual cash with current files in the editor.
;        stdcall InitVCash

; Init display strings.
;        stdcall StrNew
;        mov     [strDisplay], eax
;        mov     [iLastIcon], -1
;        mov     [hLastMsg], TVI_ROOT

; Init filename string
;        stdcall ConvertPath, [.hFileName]
        	mov eax,[.hFileName]

	mov     [hStrFileName], eax
;stdcall DisplayBlock,[hStrFileName]

;        stdcall StrPtr, eax
;        mov     [input_file], eax
;;        mov     [output_file], 0

;	invoke  GetFullPathName, eax, 1000h, path_buffer, param_buffer
;		push param_buffer
;		push path_buffer
;		push 1000h
;		push eax
;		call GetFullPathName

;	mov     edi,[param_buffer]
;	xor     al,al
;	stosb
;	invoke  SetCurrentDirectory, path_buffer

        mov     [hfile],0

        mov     [error_data_size],0
        mov     [memory_start],0

        mov     eax, [compiler_memory]
        shl     eax,10
        jz      .out_of_memory

.allocate_memory:
        mov     edx,eax
        shr     edx,3
        mov     ecx,eax
        sub     ecx,edx
        mov     [memory_end],ecx
        mov     [additional_memory_end],edx

;        invoke  HeapAlloc, [hHeap], 0, eax
                 push eax
                 call getMem
                 add esp,4

        or      eax,eax
        jnz     .memory_allocated

        mov     eax, [additional_memory_end]
        shl     eax, 2
        cmp     eax, 4000h
        jb      .out_of_memory
        jmp     .allocate_memory

.memory_allocated:
        mov     [ptrMemoryAllocated], eax       ; independent pointer to allocated block.
        mov     [memory_start],eax
        mov     [code_start],eax
        add     eax,[memory_end]
        mov     [memory_end],eax
        mov     [additional_memory],eax
        add     [additional_memory_end],eax
        mov     [display_buffer],0

	popa

        xor     eax, eax
        inc     eax
        return

.out_of_memory:
;        stdcall StrDel, [strDisplay]
;        stdcall StrDel, [hStrFileName]

	popa
	
        xor     eax, eax
        return
endp


;----------------------------------------------------------
; Free compiling resources.
; Frees all memory used by compiler, dynamic strings, etc.
; It is good to be called from main thread. (also in case of
; canceling compilation.
;----------------------------------------------------------
proc CleanupAfterCompilation
begin
        mov     eax,[ptrMemoryAllocated]
        or      eax,eax
        jz      .memory_ok

;        invoke  HeapFree, [hHeap], 0, eax
                 push eax
                 call freeMem
                 pop eax ;add esp,4

        mov     [memory_start],0
        mov     [ptrMemoryAllocated], 0

.memory_ok:
        mov     ebx,[hfile]
        or      ebx,ebx
        jz      .handle_ok

        call    close

.handle_ok:
;        stdcall StrDel, [hStrFileName]
;        stdcall StrDel, [strDisplay]

;        stdcall DestroyVCash

        return
endp



;---------------------------------------------
; Compiles the file with filename in lParam
; You can use this procedure with stdcall
; or with CreateThread.
;---------------------------------------------
;align 16
proc flat_assembler, .dummy
begin
        pushad

        mov     [save_stack_pointer], esp

;        invoke  SetThreadPriority,[hthread],[compiler_priority]

;        stdcall  GetTickCount
;        mov     [start_time],eax

; Preprocessing
;        stdcall DisplayBlock, cMsgPreprocess
  call preprocessor
;        stdcall ProgressWndStepIt
;        stdcall  GetTickCount
;        mov     [preprocess_time],eax

; Parsing
;        stdcall DisplayBlock, cMsgParsing
  call parser
;        stdcall ProgressWndStepIt
;        stdcall  GetTickCount
;        mov     [parsing_time],eax

; Creating labels list
;        stdcall CreateLabelsList, [labels_list], [memory_end]
;        stdcall ProgressWndStepIt
;        stdcall  GetTickCount
;        mov     [capturing_time],eax

; Assembling
;	stdcall DisplayBlock, cMsgAssembling
  call assembler
;        stdcall ProgressWndStepIt
;        stdcall  GetTickCount
;        mov     [assembling_time],eax

;  call InitDebugInfo
;  call lastpass

;        stdcall ProgressWndStepIt
;        stdcall  GetTickCount
;        mov     [last_pass_time],eax

; Capturing labels values.
;        stdcall CaptureLabelValues, ptrLabels
;        stdcall ProgressWndStepIt
;        stdcall  GetTickCount
;        mov     [values_time],eax

; Format output file.
;        stdcall DisplayBlock, cMsgFormating
  call    formatter

;        cmp     [CompiledFileName], 0
;        je      @f
;        stdcall StrDel, [CompiledFileName]
;        mov     [CompiledFileName], 0
;@@:
;        cmp     [output_file], 0
;        je      @f
;        stdcall StrDup, [output_file]
;        mov     [CompiledFileName], eax
;@@:
;        stdcall ProgressWndStepIt
        call    flush_display_buffer

;        stdcall  GetTickCount
;        mov     [total_time], eax

;        invoke  LockWindowUpdate, [tvMessages]

; Compilation summary display message:
;        mov     [fmsg.link.hFileName], 0
;        mov     [fmsg.type], mtInfo
;        mov     [fmsg.hMessage], cSummary
;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, TVI_ROOT
;        mov     ebx, eax
;	stdcall DisplayBlock,cSummary


;	mov     eax, [TotalLines]
;	dec     eax
;	stdcall NumToStr, eax, 0, 0, ntsZeroTerminated or ntsUnsigned or ntsDec
;	mov     esi, eax
;;        mov     [fmsg.hMessage], eax
;	stdcall StrInsert, esi, cTotalLines, 0
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;	stdcall DisplayBlock,[esi]

;        mov     eax, [AsmLines]
;        stdcall NumToStr, eax, esi, 0, ntsZeroTerminated or ntsUnsigned or ntsDec
;        stdcall StrInsert, esi, cAsmLines, 0
;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;
;        stdcall StrDel, esi

;        mov     eax, [total_time]
;        sub     eax, [start_time]
;        stdcall FormatTime, eax, cCompileTime
;        mov     [fmsg.hMessage], eax
;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]

;        push    ebx
;        mov     ebx, eax
;
;        mov     eax, [preprocess_time]
;        sub     eax, [start_time]
;        stdcall FormatTime, eax, cPreprocessTime
;;        mov     [fmsg.hMessage], eax
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]
;
;        mov     eax, [parsing_time]
;        sub     eax, [preprocess_time]
;        stdcall FormatTime, eax, cParsingTime
;;        mov     [fmsg.hMessage], eax
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]
;
;        mov     eax, [capturing_time]
;        sub     eax, [parsing_time]
;        stdcall FormatTime, eax, cCapturingTime
;;        mov     [fmsg.hMessage], eax
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]
;
;        mov     eax, [assembling_time]
;        sub     eax, [capturing_time]
;        stdcall FormatTime, eax, cAssemblingTime
;;        mov     [fmsg.hMessage], eax
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]
;
;        mov     eax, [last_pass_time]
;        sub     eax, [assembling_time]
;        stdcall FormatTime, eax, cLastPassTime
;;        mov     [fmsg.hMessage], eax
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]
;
;        mov     eax, [values_time]
;        sub     eax, [last_pass_time]
;        stdcall FormatTime, eax, cValuesTime
;;        mov     [fmsg.hMessage], eax
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]
;
;        mov     eax, [total_time]
;        sub     eax, [values_time]
;        stdcall FormatTime, eax, cFormatTime
;;        mov     [fmsg.hMessage], eax
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;        stdcall StrDel, eax ;[fmsg.hMessage]
;
;;        invoke  SendMessage, [tvMessages], TVM_EXPAND, TVE_COLLAPSE, ebx
;
;        pop     ebx
;
;;        invoke  LockWindowUpdate, NULL
;
;	movzx   eax, [current_pass]
;	inc     eax
;	stdcall NumToStr, eax, 0, 0, ntsZeroTerminated or ntsUnsigned or ntsDec
;	mov     esi, eax
;;        mov     [fmsg.hMessage], eax
;        stdcall StrInsert, esi, cCompilePasses, 0
;	stdcall DisplayBlock,esi
;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx

;	stdcall NumToStr, [written_size], esi, 0, ntsZeroTerminated or ntsUnsigned or ntsDec
;	stdcall StrInsert, esi, cCompileSize, 0
;	stdcall StrCat, esi, cSizeUnits
;;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, fmsg, ebx
;	stdcall DisplayBlock,esi
;
;	stdcall StrDel, esi
	xor     al,al

;jmp .exit_program
.exit_program:
        movzx   eax, al
        mov     [exit_code], eax

        mov     eax, MR_OK
        cmp     [exit_code], 0
        je      @f
        mov     eax, MR_ABORT
@@:
;        invoke  PostMessage,[hProgressWnd], WM_COMMAND, eax, 0

        mov     esp, [save_stack_pointer]
        popad
        mov     eax, [exit_code]
        return
endp

;iglobal
;  cTotalLines    db  'Total lines:', 0
;  cAsmLines      db  'Binary code lines: ', 0
;
;  cCompileTime db 'Total time: ',0
;  cPreprocessTime db 'Preprocessing: ', 0
;  cParsingTime    db 'Parsing:', 0
;  cCapturingTime  db 'Creating labels tree: ', 0
;  cAssemblingTime db 'Assembling time: ', 0
;  cLastPassTime   db 'Additional pass time:', 0
;  cValuesTime     db 'Capturing values: ', 0
;  cFormatTime     db 'Formating time: ',0
;
;  cTimeUnits   db ' seconds',0
;  cCompilePasses db 'Passes: ', 0
;  cCompileSize   db 'Compiled: ', 0
;  cSizeUnits     db ' bytes',0
;  cSummary       db 'Compilation summary:', 0
;endg





proc FormatTime, .time, .header
begin
        push    esi
        stdcall NumToStr, [.time], NULL, 0, ntsZeroTerminated or ntsUnsigned or ntsDec
        mov     esi, eax

.addzero:
        stdcall StrLen, esi
        cmp     eax, 4
        jae     .insertdot

        stdcall StrInsertChar, esi, '0', 0
        jmp     .addzero

.insertdot:
        sub     eax, 3
        stdcall StrInsertChar, esi, '.', eax
        stdcall StrInsert, esi, [.header], 0
        stdcall StrCat, esi, cTimeUnits

        mov     eax, esi
        pop     esi
        return
endp


;---------------------------------------------------------------------
; This is part of interface subroutines since FASM1.52
;---------------------------------------------------------------------
get_environment_variable:
;        invoke  GetPrivateProfileString, _section_environment, esi, path_buffer, edi, $1000, [ptrIniPath]
                 xor eax,eax

        add     edi,eax
;        cmp     edi,[memory_end]
;        jae     out_of_memory
        retn



;-----------------------------------------------------------------------------------------------
; Opens "virtual file" and returns pointer to the structure TVFile
; If the file is in the editor - load the virtual file from editor.
; if the file is on the disk, reads the entire file in the virtual file.
;-----------------------------------------------------------------------------------------------
open:
;        stdcall CheckCash, edx
;        test    eax, eax
;        jnz     .openfromcash
                 cmp byte [edx],'@'
                 jz .openfromcash

        stdcall  CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0
        cmp     eax,-1
        je      file_error
        mov     [hfile],eax
        mov     ebx,eax
        clc
        ret

.openfromcash:
;        mov     ebx, eax
;        stdcall VSetFilePointer, ebx, 0, FILE_BEGIN

;                 xor ebx,ebx
		mov ebx,1
		mov [hfile],ebx

	clc
	ret

    file_error:
        stc
        ret

;-----------------------------------------------------------------------------------------------
;convert_path:
;        push    ebx esi edi
;        mov     esi,edx
;        mov     edi,buffer
;
;      copy_path:
;        lods    byte [esi]
;        cmp     al,'%'
;        je      environment_variable
;        stos    byte [edi]
;        or      al,al
;        jnz     copy_path
;        cmp     edi,buffer+1000h
;        ja      out_of_memory
;        mov     eax,edi
;        pop     edi esi ebx
;        ret
;
;   environment_variable:
;        mov     ebx,esi
;
;      find_variable_end:
;        lods    byte [esi]
;        or      al,al
;        jz      not_environment_variable
;        cmp     al,'%'
;        jne     find_variable_end
;        mov     byte [esi-1],0
;        invoke  GetEnvironmentVariable,ebx,path_buffer,1000h
;        mov     eax,buffer+1000h
;        sub     eax,edi
;        invoke  GetPrivateProfileString,_section_environment,ebx,path_buffer,edi,eax, [ptrIniPath]
;        add     edi,eax
;        mov     byte [esi-1],'%'
;        jmp     copy_path
;
;      not_environment_variable:
;        mov     al,'%'
;        stos    byte [edi]
;        mov     esi,ebx
;        jmp     copy_path

;**********************************************************
; Convert path wrapper for common use outside compiler.
; Returns string handle to converted name.
; returns in edx pointer to the end of the name.
;**********************************************************
proc ConvertPath, .hFileName
.res dd ?
.env rb 512
.ini rb 512
.strend dd ?
begin
        push    ebx edi esi

        stdcall StrNew
        mov     [.res], eax

        stdcall StrSetLength, [.res], 512
        mov     edi, eax
        add     eax, 512
        mov     [.strend], eax

        stdcall StrPtr, [.hFileName]
        mov     esi, eax

.copy_path:
        lods    byte [esi]
        cmp     al,'%'
        je      .envvariable
        stos    byte [edi]
        test    al,al
        jnz     .copy_path

        mov     edx,edi
        mov     eax, [.res]
        pop     esi edi ebx
        return

.envvariable:
        mov     ebx,esi

.find_var_end:
        lods    byte [esi]
        or      al,al
        jz      .not_env_var
        cmp     al,'%'
        jne     .find_var_end

        mov     byte [esi-1],0

        lea     ecx, [.env]
;        invoke  GetEnvironmentVariable, ebx, ecx, 512
                 xor eax,eax

        mov     byte [.env+eax], 0
        mov     eax, [.strend]
        sub     eax,edi

        lea     ecx, [.env]
;        invoke  GetPrivateProfileString, _section_environment, ebx, ecx, edi, eax, [ptrIniPath]
                 xor eax,eax

        add     edi,eax
        mov     byte [esi-1],'%'
        jmp     .copy_path

.not_env_var:
        mov     al,'%'
        stos    byte [edi]
        mov     esi,ebx
        jmp     .copy_path
endp

;------------------------------------------------------------------------------------------------

create:
;	cmp byte [edx],'@'
;	jnz @f
;	
;	stdcall  CreateFile,szTst,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
;	cmp     eax,-1
;	je      file_error
;	mov     ebx,eax
;	clc
;	ret
;
;@@:
        stdcall  CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
        cmp     eax,-1
        je      file_error
        mov     ebx,eax
        clc
        ret

;------------------------------------------------------------------------------------------------

write:
        stdcall  WriteFile,ebx,edx,ecx,bytes_count,0
        or      eax,eax
        jz      file_error
        clc
        ret

;------------------------------------------------------------------------------------------------

read:
;        test    ebx, $ffff0000
;        jnz     .readfromcash
;                 test ebx,ebx
		cmp ebx,1
		jz .readfromcash

        mov     ebp,ecx
        stdcall  ReadFile,ebx,edx,ecx,bytes_count,0
        or      eax,eax
        jz      file_error
        cmp     ebp,[bytes_count]
        jne     file_error
        clc
        ret

.readfromcash:
;        mov     ebp, ecx
;        stdcall VReadFile, ebx, edx, ecx
;        cmp     ebp, eax
;        jne     file_error
                mov eax,[pos_in_func_to_compile]
                push ebx
                push ecx
                push edx

                push ecx

                mov ebx,[size_of_func_to_compile]
                add ebx,[lpszFunc_to_compile]
                sub ebx,[pos_in_func_to_compile]
                cmp ebx,ecx
                jnc @f

                mov ecx,ebx
        @@:

                push ecx

                mov ebx,ecx
                add ebx,[pos_in_func_to_compile]
                mov [pos_in_func_to_compile],ebx

push edx
push ecx

;pusha
;stdcall prhex, eax
;popa

                push ecx
                push eax
                push edx
                call cpyMem
                add esp,4*3

pop ecx
pop edx

                pop eax
                pop ebx

                cmp eax,ebx
                pop edx
                pop ecx
                pop ebx
                jc file_error

        clc
        ret

;------------------------------------------------------------------------------------------------

close:
        cmp     ebx,[hfile]
        jne     close_handle

        cmp ebx,1
        jnz @f
        xor ebx,ebx
  @@:
        mov     [hfile],0
  close_handle:
;        test    ebx, $ffff0000
;        jnz     .closed
                 test ebx,ebx
                 jz .closed

        stdcall  CloseHandle,ebx
.closed:
        ret



;------------------------------------------------------------------------------------------------

lseek:
;        test    ebx, $ffff0000
;        jnz     .seekcash
;                 test ebx,ebx
		cmp ebx,1
		jz .seekcash


        movzx   eax,al
        stdcall  SetFilePointer,ebx,edx,0,eax
        cmp     eax,-1
        je      file_error
        ret

.seekcash:
;        movzx   eax, al
;        stdcall VSetFilePointer, ebx, edx, eax
                test al,al
                jnz @f

		mov eax,[lpszFunc_to_compile]
		add eax,edx
                mov [pos_in_func_to_compile],eax
                mov eax,edx
                ret
        @@:
                dec al
                jnz @f

                mov eax,[pos_in_func_to_compile]
                add eax,edx
                mov [pos_in_func_to_compile],eax
                ret
        @@:
                dec al
                jnz @f

		mov eax,[size_of_func_to_compile]
		sub eax,edx
		push eax
		add eax,[lpszFunc_to_compile]
		mov [pos_in_func_to_compile],eax
		pop eax
        @@:

        ret

;------------------------------------------------------------------------------------------------

;uglobal
;  strDisplay dd ?
;  iLastIcon  dd ?
;  hLastMsg   dd ?
;endg

proc display_block
;.fmsg TFreshMsg
begin

;mov eax,dword [esp+4]
;push eax
;call Print
;pop eax

        push    ebx
        mov     byte [esi+ecx], 0

		push esi
		call Print
		pop eax

;.loopskip:
;        mov     edx, esi

;.lineloop:
;; Check for eol.
;	lodsb
;	test    al,al
;	jz      .eol
;	cmp     al,$0d
;	je      .eol
;	cmp     al,$0a
;	je      .eol
;	cmp     al,$09
;	je      .eol
;	cmp     al,$08
;	je      .eol

;	cmp     al, 5
;	ja      .lineloop
;
;.eol:
;	mov     bl,al
;	mov     byte [esi-1], 0
;        stdcall StrCat, [strDisplay], edx
;
;        test    bl, bl
;        jz      .finish
;        cmp     bl, $0d
;        je      .eol2
;        cmp     bl, $0a
;        je      .eol2
;        cmp     bl, $09
;        je      .eol2
;        cmp     bl, $08
;        je      .eol2
;
;        movzx   ebx, bl
;        dec     ebx
;        mov     [iLastIcon], ebx
;        jmp     .loopskip
;
;.eol2:
;        stdcall StrPtr, [strDisplay]
;        cmp     byte [eax], 0
;        je      .loopskip               ; Don't append empty messages.
;
;        push    [iLastIcon] [strDisplay]
;        pop     [.fmsg.hMessage] [.fmsg.type]
;        and     [.fmsg.link.hFileName], 0
;        lea     eax, [.fmsg]
;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, eax, [hLastMsg]
;
;        cmp     bl, $0d
;        je      .cr
;        cmp     bl, $0a
;        je      .end
;        cmp     bl, $09
;        je      .set
;
;.back:
;        invoke  SendMessage, [tvMessages], TVM_GETNEXTITEM, TVGN_PARENT, [hLastMsg]
;        jmp     .set
;.cr:
;        mov     eax, TVI_ROOT
;.set:
;        mov     [hLastMsg], eax
;.end:
;        stdcall StrPtr, [strDisplay]
;        mov     byte [eax], 0
;        mov     [iLastIcon], -1
;        jmp     .loopskip
;
.finish:
        pop     ebx
        return
endp



proc DisplayBlock, .hString
begin
return
;	pushad
	push eax
;	stdcall StrNew
;	stdcall StrCopy, eax, [.hString]
;	push    eax
;
;	stdcall StrPtr, eax
;	mov     esi, eax
;
;	stdcall StrLen, [.hString]
;	mov     ecx, eax
;
;	call    display_block
push [.hString]
call Print
pop eax

;	stdcall StrDel  ; arg is in the stack.
	pop eax
;	popad
	return
endp



proc AppendErrorMessage, .filename, .linenum, .parent, .emsg
;.FMsg TFreshMsg
;.name rb 512
;.ptr  dd ?
begin
;        pushad
;
;        mov     [.FMsg.type], mtError
;        push    [.linenum]
;        push    [.linenum]
;        pop     [.FMsg.link.pos.caretLine]
;        pop     [.FMsg.link.pos.selectionLine]
;        mov     [.FMsg.link.hFileName], 0
;        mov     [.FMsg.link.pos.caretPosition], 1
;        mov     [.FMsg.link.pos.selectionPosition], 257
;
;        stdcall StrNew
;        mov     [.FMsg.hMessage], eax
;        mov     esi, eax
;
;        cmp     [.emsg], NULL
;        je      .nomessage
;
;        stdcall StrCopy, esi, cErrorPrefix
;        stdcall StrCat, esi, [.emsg]
;
;.nomessage:
;        cmp     [.filename], NULL
;        je      .messageready
;
;        stdcall StrPtr, [.filename]
;        lea     edi, [.name]
;        lea     ecx, [.ptr]
;        invoke  GetFullPathName, eax, 512, edi, ecx
;
;        mov     [.FMsg.link.hFileName], edi
;
;        stdcall StrPtr, esi
;        stdcall StrCat, esi, [.ptr]
;        stdcall StrCat, esi, cLMiddleBracket
;        stdcall NumToStr, [.linenum], NULL, 0, ntsZeroTerminated or ntsUnsigned or ntsDec
;        stdcall StrCat, esi, eax
;        stdcall StrDel, eax
;        stdcall StrCat, esi, cRMiddleBracket
;
;.messageready:
;        lea     eax, [.FMsg]
;        invoke  SendMessage, [frmMsg], MWM_ADDMESSAGE, eax, [.parent]
;        mov     [.ptr], eax
;        stdcall StrDel, esi
;        popad
;        mov     eax, [.ptr]
        return
endp


;iglobal
;  cMsgPreprocess db 3, 'Preprocessing...',13,0
;  cMsgParsing    db 3, 'Parsing...',13,0
;  cMsgAssembling db 3, 'Assembling...',13,0
;  cMsgFormating  db 3, 'Formating...',13,0
;
;  cLMiddleBracket db ' [',0
;  cRMiddleBracket db ']',0
;
;  cErrorPrefix   db 'Error: ', 0
;endg


;------------------------------------------------------------------------------------------------
fatal_error:
        call    flush_display_buffer
;        stdcall AppendErrorMessage, NULL, -1, TVI_ROOT    ; the error message address is in the stack.
		push dword [esp+4]
		call Error
		pop eax

        mov     al,0FFh
        jmp     flat_assembler.exit_program


;szTst	db "tst",0
;szErr db "err",0

assembler_error:
        call    flush_display_buffer

;push szErr
;call printf
;pop eax

        pop     esi
        mov     edi, buffer

.copymessage:
        lodsb
        stosb
        test    al,al
        jnz     .copymessage

        dec     edi
        mov     eax, ' << '
        stosd

        mov     esi,[current_line]
        test    esi,esi
        jz      instruction_converted
        add     esi,16
        xor     dl,dl

      convert_instruction:
        lodsb
        cmp     al,1Ah
        je      copy_symbol
        cmp     al,22h
        je      copy_symbol
        cmp     al,3Bh
        je      ignore_preprocessor_symbols
        stosb
        or      al,al
        jz      instruction_converted
        xor     dl,dl
        jmp     convert_instruction
      copy_symbol:
        or      dl,dl
        jz      space_ok
        mov     byte [edi],20h
        inc     edi
      space_ok:
        cmp     al,22h
        je      quoted
        lodsb
        movzx   ecx,al
        rep     movsb
        or      dl,-1
        jmp     convert_instruction
      quoted:
        mov     al,27h
        stosb
        lodsd
        mov     ecx,eax
        jecxz   quoted_copied
      copy_quoted:
        lodsb
        stosb
        cmp     al,27h
        jne     quote_ok
        stosb
      quote_ok:
        loop    copy_quoted
      quoted_copied:
        mov     al,27h
        stosb
        or      dl,-1
        jmp     convert_instruction
      ignore_preprocessor_symbols:
        xor     al,al
        stosb
      instruction_converted:

        dec     edi
        mov     eax, ' >> '
        stosd
        mov     byte [edi], 0

        mov     edi, buffer

        push    dword 0
        mov     ebx,[current_line]

;        mov     ecx, TVI_ROOT

  get_error_lines:
        push    ebx
        test    byte [ebx+7], 80h       ; First if not set ???
        jz      display_error_line

        pop     ebx
        mov     edx,ebx

  find_definition_origin:
        mov     edx,[edx+12]
        test    byte [edx+7],80h
        jnz     find_definition_origin

        push    edx
        mov     ebx,[ebx+8]
        jmp     get_error_lines

  display_error_line:
        pop     ebx
        test    ebx, ebx
        jz      finish_error
        mov     esi,[ebx]
        mov     eax,[ebx+4]
;        stdcall AppendErrorMessage, [ebx], [ebx+4], ecx, edi

		push eax

		push esi ;dword [ebx]
		call Error
		pop eax
		
;		push dword [ebx+4]
;		call Error
;		pop eax
		
		push edi
		call Error
		pop eax

		pop eax

; uncomment if you want only one level of nesting error messages.
; Maybe it's interesting if the style of the message treeview
; includes TVS_SINGLEEXPAND style.
;        cmp     ecx, TVI_ROOT
;        jne     display_error_line

        xor     edi, edi
        mov     ecx, eax
        jmp     display_error_line

  finish_error:
        mov     al,2
        jmp     flat_assembler.exit_program

;------------------------------------------------------------------------------------------------

mark_relocation:
		ret

;------------------------------------------------------------------------------------------------

make_timestamp:
        invoke  GetSystemTime, systime

        movzx   ecx, [systime.wYear]
        mov     eax,ecx
        sub     eax,1970
        mov     ebx,365
        mul     ebx
        mov     ebp,eax
        mov     eax,ecx
        sub     eax,1969
        shr     eax,2
        add     ebp,eax
        mov     eax,ecx
        sub     eax,1901
        mov     ebx,100
        div     ebx
        sub     ebp,eax
        mov     eax,ecx
        xor     edx,edx
        sub     eax,1601
        mov     ebx,400
        div     ebx
        add     ebp,eax
        movzx   ecx, [systime.wMonth]
        mov     eax,ecx
        dec     eax
        mov     ebx,30
        mul     ebx
        add     ebp,eax
        cmp     ecx,8
        jbe     .months_correction
        mov     eax,ecx
        sub     eax,7
        shr     eax,1
        add     ebp,eax
        mov     ecx,8
.months_correction:
        mov     eax,ecx
        shr     eax,1
        add     ebp,eax
        cmp     ecx,2
        jbe      .months_correction_ok

        sub     ebp,2

.months_correction_ok:
        cmp     ecx,2
        jbe     .day_correction_ok

        movzx   ecx, [systime.wYear]
        test    ecx,11b

        jnz     .day_correction_ok
        xor     edx,edx
        mov     eax,ecx
        mov     ebx,100
        div     ebx
        or      edx,edx
        jnz     .day_correction
        mov     eax,ecx
        mov     ebx,400
        div     ebx
        or      edx,edx
        jnz     .day_correction_ok

.day_correction:
        inc     ebp

.day_correction_ok:
        movzx   eax,[systime.wDay]
        dec     eax
        add     eax,ebp
        mov     ebx,24
        mul     ebx
        movzx   ecx, [systime.wHour]
        add     eax,ecx
        mov     ebx,60
        mul     ebx
        movzx   ecx, [systime.wMinute]
        add     eax,ecx
        mov     ebx,60
        mul     ebx
        movzx   ecx,word [systime.wSecond]
        add     eax,ecx
        ret

;------------------------------------------------------------------------------------------------

